#include "Device.h"

Device::Device(const char *device) {
	openedDevice = ::open(device, O_RDONLY);

	if (openedDevice < 0) {
		perror(device);
		exit(1);
	}

	cache = new map<int, Blok*>;
}

Device::~Device() {
	for(map<int,Blok*>::iterator iter = cache->begin(); iter != cache->end(); ++iter){
		delete iter->second;
	}
	delete cache;
	close(openedDevice);
}

Blok* Device::getBlok(int number){
	map<int, Blok*>::iterator cachedBlockPair = cache->find(number);
	if (cachedBlockPair != cache->end()) {
		cachedBlockPair->second->incrementUsecount();

		return cachedBlockPair->second;
	}

	byte buffer[DBLKSIZ];

	::lseek( openedDevice, DBLKSIZ*number, SEEK_SET );
	::read( openedDevice, buffer, DBLKSIZ );

	Blok* result = new Blok(buffer);

	addBlockToCache(number, result);

	result->incrementUsecount();
	return result;
}

void Device::addBlockToCache(int number, Blok* block) {
	// Als de cache vol is, haal het minst gebruikte blok eruit.
	if (cache->size() >= CACHESZ) {
		map<int, Blok*>::iterator minUsed = cache->begin();
		for (map<int, Blok*>::iterator iter = cache->begin(); iter != cache->end(); ++iter) {
			if (iter->second->getUsecount() < minUsed->second->getUsecount())
				minUsed = iter;
		}

		delete minUsed->second;
		cache->erase(minUsed);
	}

	cache->insert( pair<int, Blok*>( number, block ) );
}

SuperBlok* Device::getSuperBlok() {
	byte buffer[DBLKSIZ];

	::lseek( openedDevice, 512, SEEK_SET );
	::read( openedDevice, buffer, DBLKSIZ );

	return new SuperBlok( buffer );
}
